package com.gopay.common.user.manager.impl;

import com.gopay.common.constants.cust.PayPasswordQuesStatus;
import com.gopay.common.constants.cust.UserInfoConstants;
import com.gopay.common.constants.proccode.ProcCodeEnum;
import com.gopay.common.constants.trans.UserType;
import com.gopay.common.domain.UserInfo;
import com.gopay.common.domain.acps.PayPasswordStatus;
import com.gopay.common.domain.cust.CustCorpInfo;
import com.gopay.common.domain.cust.CustPersonInfo;
import com.gopay.common.domain.user.UserPayPwdQuesResult;
import com.gopay.common.domain.user.UserPayPwdResult;
import com.gopay.common.user.dao.CustCorpInfoQueryDAO;
import com.gopay.common.user.dao.CustPersonInfoQueryDAO;
import com.gopay.common.user.dao.UserInfoQueryDAO;
import com.gopay.common.user.manager.UserPayPwdManager;
import com.gopay.common.util.DateUtils;
import com.gopay.common.util.NonrevEncr;
import com.gopay.common.util.pwd.UserPwdUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Calendar;
import java.util.Date;

/**
 * @UserPayPwdManagerImpl.java
 * @author HJY
 * @2013-5-22 上午11:58:58 www.gopay.com.cn Inc.All rights reserved.
 */
@Service("userPayPwdManager")
public class UserPayPwdManagerImpl implements UserPayPwdManager {

    @Resource(name = "custCorpInfoQueryDao")
    private CustCorpInfoQueryDAO custCorpInfoQueryDao;

    @Resource(name = "custPersonInfoQueryDao")
    private CustPersonInfoQueryDAO custPersonInfoQueryDao;

    @Resource(name = "userInfoQueryDao")
    private UserInfoQueryDAO userInfoQueryDao;

    @Override
    public UserPayPwdResult verifyPayPwd(String userId, String payPwd) {
        boolean verify = false;

        UserPayPwdResult result = new UserPayPwdResult(verify, 0, 0, null, null);
        if (StringUtils.isBlank(userId) || StringUtils.isBlank(payPwd)) {
            result.setErrorMsg("支付密码不能为空");
            result.setErrorCode(ProcCodeEnum.PROC_CODE_100E3007.getCode());
            return result;
        }

        UserInfo ui = userInfoQueryDao.find(UserInfo.class, userId);
        if (ui == null) {
            result.setErrorMsg("can't find user while userId is " + userId);
            return result;
        }

        String errorMsg = "";
        String custId = ui.getCustId();
        String custType = ui.getUserType();
        
        if (UserType.Person.value.equals(custType)) {
            CustPersonInfo ci = custPersonInfoQueryDao.find(CustPersonInfo.class, custId);

            // 校验支付密码是否锁定
            if (PayPasswordStatus.NORMAL.ordinal() != ci.getPayPwdStatus()) {
                result.setPayPwdStatus(PayPasswordStatus.get(ci.getPayPwdStatus()));
                result.setTodayErrCount(ci.getTodayPwdErrNum());
                result.setTotalErrCount(ci.getTotalPwdErrNum());
                result.setErrorMsg("支付密码被锁定，可通过“找回支付密码”解锁，或联系客服完成支付密码解锁");
                result.setErrorCode(ProcCodeEnum.PROC_CODE_100E3022.getCode());
                return result;
            }

            // edit hougn 2017-01-05 pci认证,sha1修改为sha512  start
            StringBuilder sb=new StringBuilder(custId.trim());
            sb.append(payPwd.trim());
            
            // 支付密码输入错误
            if (!UserPwdUtil.checkPwd(ci.getPayPwd(), sb)) {
            // edit hougn 2017-01-05 pci认证,sha1修改为sha512  end
                errorMsg = "支付密码输入错误，请重新输入";
                if(ci.getTodayPwdErrNum()<UserInfoConstants.MAX_PAYPWD_DAY_ERR){
                    ci.setTodayPwdErrNum(ci.getTodayPwdErrNum() + 1);
                }
                if(ci.getTodayPwdErrNum() == UserInfoConstants.MAX_PAYPWD_DAY_ERR){
                    ci.setPayPwdStatus(PayPasswordStatus.LOCK_PERMANENT.ordinal());
                    ci.setPayPwdLockTime(new Date());
                    errorMsg = "支付密码输错次数已达上限，支付密码被锁定。 可通过“找回支付密码”解锁，或联系客服完成支付密码解锁";
                }
                ci.setTotalPwdErrNum(ci.getTotalPwdErrNum() + 1);
                custPersonInfoQueryDao.update(ci);
            } else {
                verify = true;
                // edit hougn 2017-01-05 pci认证,sha1修改为sha512  start
                if (UserPwdUtil.isSHA1(ci.getPayPwd())) {
                    ci.setPayPwd(NonrevEncr.sha512(sb));
                }
                // edit hougn 2017-01-05 pci认证,sha1修改为sha512  end
                ci.setTodayPwdErrNum(0);
                ci.setPayPwdStatus(PayPasswordStatus.NORMAL.ordinal());
                custPersonInfoQueryDao.update(ci);
            }
            return makePersonPayPwdResult(custId, custType, verify, errorMsg);
        } else {
            CustCorpInfo ci = custCorpInfoQueryDao.find(CustCorpInfo.class, custId);

            // 校验支付密码是否锁定
            if (PayPasswordStatus.NORMAL.ordinal() != ci.getPayPwdStatus()) {
                result.setErrorMsg("支付密码被锁定，可通过“找回支付密码”解锁，或联系客服完成支付密码解锁");
                result.setErrorCode(ProcCodeEnum.PROC_CODE_100E3022.getCode());
                return result;
            }

            // edit hougn 2017-01-05 pci认证,sha1修改为sha512  start
            StringBuilder sb=new StringBuilder(custId.trim());
            sb.append(payPwd.trim());
            
            // 支付密码校验错误
            if (!UserPwdUtil.checkPwd(ci.getPayPwd(), sb)) {
            // edit hougn 2017-01-05 pci认证,sha1修改为sha512  end
                errorMsg = "支付密码输入错误，请重新输入";
                if(ci.getTodayPwdErrNum()<UserInfoConstants.MAX_PAYPWD_DAY_ERR){
                    ci.setTodayPwdErrNum(ci.getTodayPwdErrNum() + 1);
                    //云账户网关支付支付密码错误信息提示     jiaoshuai 20160728
                    result.setTodayErrCount(ci.getTodayPwdErrNum());
                }
                if(ci.getTodayPwdErrNum() == UserInfoConstants.MAX_PAYPWD_DAY_ERR){
                    ci.setPayPwdStatus(PayPasswordStatus.LOCK_PERMANENT.ordinal());
                    ci.setPayPwdLockTime(new Date());
                    //云账户网关支付支付密码错误信息提示     jiaoshuai 20160728
                    result.setPayPwdStatus(PayPasswordStatus.LOCK_PERMANENT);
                    errorMsg = "支付密码输错次数已达上限，支付密码被锁定。 可通过“找回支付密码”解锁，或联系客服完成支付密码解锁";
                }
                ci.setTotalPwdErrNum(ci.getTotalPwdErrNum() + 1);
                custCorpInfoQueryDao.update(ci);
            } else {
                verify = true;
                // edit hougn 2017-01-05 pci认证,sha1修改为sha512  start
                if (UserPwdUtil.isSHA1(ci.getPayPwd())) {
                    ci.setPayPwd(NonrevEncr.sha512(sb));
                }
                // edit hougn 2017-01-05 pci认证,sha1修改为sha512  end
                ci.setTodayPwdErrNum(0);
                ci.setPayPwdStatus(PayPasswordStatus.NORMAL.ordinal());
                custCorpInfoQueryDao.update(ci);
            }
            
            return makeCorpUserPayPwdResult(custId, custType, verify, errorMsg);
        }
    }

    private UserPayPwdResult makePersonPayPwdResult(String custId, String userType, boolean verify, String errorMsg) {
        UserPayPwdResult result = new UserPayPwdResult();
        CustPersonInfo ci = custPersonInfoQueryDao.find(CustPersonInfo.class, custId);
        result.setPayPwdStatus(PayPasswordStatus.get(ci.getPayPwdStatus()));
        result.setTodayErrCount(ci.getTodayPwdErrNum());
        result.setTotalErrCount(ci.getTotalPwdErrNum());
        result.setVerifySuccess(verify);
        result.setUserType(UserType.get(userType));
        if (StringUtils.isNotBlank(errorMsg)) {
            result.setErrorMsg(errorMsg);
        }
        return result;
    }

    private UserPayPwdResult makeCorpUserPayPwdResult(String custId, String userType, boolean verify, String errorMsg) {
        UserPayPwdResult result = new UserPayPwdResult();
        CustCorpInfo ci = custCorpInfoQueryDao.find(CustCorpInfo.class, custId);
        result.setPayPwdStatus(PayPasswordStatus.get(ci.getPayPwdStatus()));
        result.setTodayErrCount(ci.getTodayPwdErrNum());
        result.setTotalErrCount(ci.getTotalPwdErrNum());
        result.setVerifySuccess(verify);
        result.setUserType(UserType.get(userType));
        if (StringUtils.isNotBlank(errorMsg)) {
            result.setErrorMsg(errorMsg);
        }
        return result;
    }

    @Override
    public UserPayPwdQuesResult verifySafeQues(String userId,String answer) {
        UserInfo ui = userInfoQueryDao.find(UserInfo.class, userId);
        UserPayPwdQuesResult result = new UserPayPwdQuesResult(null,false,0,null,null);
        if (ui != null) {
            result.setUserType(UserType.get(ui.getUserType()));
            String custId = ui.getCustId();
            String custType = ui.getUserType();
            StringBuilder sb=new StringBuilder(custId.trim());
            sb.append(answer.trim());

            if (UserType.Person.value.equals(custType)) {
                String errorMsg = "您的安全问题答案已连续输入错误"+UserInfoConstants.PERSON_MAX_PAYPWD_SAFEQUES_DAY_ERR+"次，在三小时之内不能进行找回支付密码找回操作，您也可通过客服人工找回密码";
                CustPersonInfo ci = custPersonInfoQueryDao.find(CustPersonInfo.class, custId);
                // 当安全问题及答案输入错误到达5次，则找回支付密码功能3小时内（含）不可用
                if ((ci.getTotalPwdQusErrNum() >= UserInfoConstants.PERSON_MAX_PAYPWD_SAFEQUES_DAY_ERR) && !checkTime(ci.getPayPwdQusLockTime())) {
                    result.setErrorMsg(errorMsg);
                    result.setPayPwdQuesStatus(PayPasswordQuesStatus.get(ci.getPayQusAnsStatus()));
                    result.setTotalErrCount(ci.getTotalPwdQusErrNum());
                    return result;
                }
                
                // edit hougn 2017-01-05 pci认证,sha1修改为sha512  start
                if ((!UserPwdUtil.checkPwd(ci.getPayQusAnswer(), sb))) {
                // edit hougn 2017-01-05 pci认证,sha1修改为sha512  end
                    ci.setTotalPwdQusErrNum(ci.getTotalPwdQusErrNum() + 1);
                    if (UserInfoConstants.PERSON_MAX_PAYPWD_SAFEQUES_DAY_ERR == ci.getTotalPwdQusErrNum()) {
                        ci.setPayQusAnsStatus(PayPasswordQuesStatus.LOCK_ONEDAY.ordinal());
                        ci.setPayPwdQusLockTime(new Date());
                        result.setErrorMsg(errorMsg);
                    }else{
                        result.setErrorMsg("您的安全问题答案已错误 "+ci.getTotalPwdQusErrNum()+" 次");
                    }
                } else {
                    result.setVerifySuccess(true);
                    // edit hougn 2017-01-05 pci认证,sha1修改为sha512  start
                    if(UserPwdUtil.isSHA1(ci.getPayQusAnswer())){
                        ci.setPayQusAnswer(NonrevEncr.sha512(sb));
                    }
                    // edit hougn 2017-01-05 pci认证,sha1修改为sha512  end
                    ci.setTotalPwdQusErrNum(0);
                    ci.setPayQusAnsStatus(PayPasswordQuesStatus.NORMAL.ordinal());
                }
                result.setPayPwdQuesStatus(PayPasswordQuesStatus.get(ci.getPayQusAnsStatus()));
                result.setTotalErrCount(ci.getTotalPwdQusErrNum());
                custPersonInfoQueryDao.update(ci);
            } else {
                String errorMsg = "您的安全问题答案已连续输入错误"+UserInfoConstants.CORP_MAX_PAYPWD_SAFEQUES_DAY_ERR+"次，在三小时之内不能进行找回支付密码找回操作，您也可通过客服人工找回密码";
                CustCorpInfo ci = custCorpInfoQueryDao.find(CustCorpInfo.class, custId);
                // 当安全问题及答案输入错误到达10次，则找回支付密码功能3小时内（含）不可用
                if ((ci.getTotalPwdQusErrNum() >= UserInfoConstants.CORP_MAX_PAYPWD_SAFEQUES_DAY_ERR)&& !checkTime(ci.getPayPwdQusLockTime())) {
                    result.setErrorMsg(errorMsg);
                    result.setPayPwdQuesStatus(PayPasswordQuesStatus.get(ci.getPayQusAnsStatus()));
                    result.setTotalErrCount(ci.getTotalPwdQusErrNum());
                    return result;
                }
                // edit hougn 2017-01-05 pci认证,sha1修改为sha512  start
                if ((!UserPwdUtil.checkPwd(ci.getPayQusAnswer(), sb))) {
                // edit hougn 2017-01-05 pci认证,sha1修改为sha512  end
                    ci.setTotalPwdQusErrNum(ci.getTotalPwdQusErrNum() + 1);
                    if (UserInfoConstants.CORP_MAX_PAYPWD_SAFEQUES_DAY_ERR == ci.getTotalPwdQusErrNum()) {
                        ci.setPayQusAnsStatus(PayPasswordQuesStatus.LOCK_ONEDAY.ordinal());
                        ci.setPayPwdQusLockTime(new Date());
                        result.setErrorMsg(errorMsg);
                    }else{
                        result.setErrorMsg("您的安全问题答案已错误 "+ci.getTotalPwdQusErrNum()+" 次");
                    }
                } else {
                    result.setVerifySuccess(true);
                    // edit hougn 2017-01-05 pci认证,sha1修改为sha512  start
                    if(UserPwdUtil.isSHA1(ci.getPayQusAnswer())){
                        ci.setPayQusAnswer(NonrevEncr.sha512(sb));
                    }
                    // edit hougn 2017-01-05 pci认证,sha1修改为sha512  end
                    ci.setTotalPwdQusErrNum(0);
                    ci.setPayQusAnsStatus(PayPasswordQuesStatus.NORMAL.ordinal());
                }
                result.setPayPwdQuesStatus(PayPasswordQuesStatus.get(ci.getPayQusAnsStatus()));
                result.setTotalErrCount(ci.getTotalPwdQusErrNum());
                custCorpInfoQueryDao.update(ci);
            }
        }
        return result;
    }

    @Override
    public boolean updatePayPwd(String userId, String newPayPwd) {
        UserInfo ui = userInfoQueryDao.find(UserInfo.class, userId);
        if (ui != null) {
            String custId = ui.getCustId();
            String custType = ui.getUserType();
            StringBuilder sb=new StringBuilder(custId.trim());
            sb.append(newPayPwd.trim());
            if (UserType.Person.value.equals(custType)) {
                CustPersonInfo ci = custPersonInfoQueryDao.find(CustPersonInfo.class, custId);
                // edit hougn 2017-01-05 pci认证,sha1修改为sha512  start
                String vPayPwd = NonrevEncr.sha512(sb);
                // edit hougn 2017-01-05 pci认证,sha1修改为sha512  end
                ci.setPayPwd(vPayPwd);
                ci.setPayPwdStatus(PayPasswordStatus.NORMAL.ordinal());
                ci.setTodayPwdErrNum(0);
                custPersonInfoQueryDao.update(ci);
                return true;
            } else {
                CustCorpInfo ci = custCorpInfoQueryDao.find(CustCorpInfo.class, custId);
                // edit hougn 2017-01-05 pci认证,sha1修改为sha512  start
                String vPayPwd = NonrevEncr.sha512(sb);
                // edit hougn 2017-01-05 pci认证,sha1修改为sha512  end
                ci.setPayPwd(vPayPwd);
                ci.setPayPwdStatus(PayPasswordStatus.NORMAL.ordinal());
                ci.setTodayPwdErrNum(0);
                custCorpInfoQueryDao.update(ci);
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean updateSafeQues(String userId, String ques, String answer) {
        UserInfo ui = userInfoQueryDao.find(UserInfo.class, userId);
        if (ui != null) {
            String custId = ui.getCustId();
            String custType = ui.getUserType();
            StringBuilder sbQues=new StringBuilder(custId.trim());
            sbQues.append(ques.trim());
            StringBuilder sbAnswer=new StringBuilder(custId.trim());
            sbAnswer.append(answer.trim());
            if (UserType.Person.value.equals(custType)) {
                CustPersonInfo ci = custPersonInfoQueryDao.find(CustPersonInfo.class, custId);
                // edit hougn 2017-01-05 pci认证,sha1修改为sha512  start
                String vQues = NonrevEncr.sha512(sbQues);
                String vAnswer = NonrevEncr.sha512(sbAnswer);
                // edit hougn 2017-01-05 pci认证,sha1修改为sha512  end
                ci.setPayQus(vQues);
                ci.setPayQusAnswer(vAnswer);
                ci.setPayQusAnsStatus(PayPasswordQuesStatus.NORMAL.ordinal());
                ci.setTotalPwdQusErrNum(0);
                custPersonInfoQueryDao.update(ci);
                return true;
            } else {
                CustCorpInfo ci = custCorpInfoQueryDao.find(CustCorpInfo.class, custId);
                // edit hougn 2017-01-05 pci认证,sha1修改为sha512  start
                String vQues = NonrevEncr.sha512(sbQues);
                String vAnswer = NonrevEncr.sha512(sbAnswer);
                // edit hougn 2017-01-05 pci认证,sha1修改为sha512  start
                ci.setPayQus(vQues);
                ci.setPayQusAnswer(vAnswer);
                ci.setPayQusAnsStatus(PayPasswordQuesStatus.NORMAL.ordinal());
                ci.setTotalPwdQusErrNum(0);
                custCorpInfoQueryDao.update(ci);
                return true;
            }
        }
        return false;
    }


    /**
     * 校验锁定时间是否在三个小时内 如：锁定时间为10:20 当前时间为13:21 返回true
     * 
     * @param lockTime
     *            密码锁定时间
     * @return
     */
    private boolean checkTime(Date lockTime) {
        if (lockTime == null) {
            return true;
        }
        String lock = DateUtils.format(DateUtils.add(lockTime, Calendar.HOUR,
                UserInfoConstants.FIND_PAYPWD_UNAVAILABLE_TIME));
        String now = DateUtils.format(new Date());
        return Long.parseLong(now) > Long.parseLong(lock);
    }

    @Override
    public String getPayPwdStatusMsg(int errNum){
        String resmsg = null;
        if (errNum == 1) {
            resmsg = "您的支付密码输入错误,请重新获取验证码并输入正确的支付密码";
        }
        if (errNum == UserInfoConstants.MAX_PAYPWD_DAY_ERR - 1) {
            resmsg = "您的支付密码输入错误，还剩一次机会，再次错误支付密码将锁定，请谨慎操作";
        }
        if (errNum >= UserInfoConstants.MAX_PAYPWD_DAY_ERR) {
            resmsg = "您的支付密码输入错误达" + UserInfoConstants.MAX_PAYPWD_DAY_ERR + "次，支付密码已锁定,如需解锁请联系客服400-0550-009 ";
        }
        return resmsg;
    }
}
